# -*- coding: UTF-8 -*-

# @Time : 2020/9/21 15:06 

# @Author : litao

# @File : handlers.py


import time
import os
import json
import math
from datetime import datetime
from utils.LoggerUtil import logger

from tornado.web import RequestHandler
from jinja2 import Environment, FileSystemLoader, TemplateNotFound
from urllib.parse import unquote


from conf import config as conf

from utils.MyUtil import MyUtil
from utils.ResultUtil import ResultVOUtil
from utils.PageUtil import Page
from app.models import Project, Product, Room, RoomLibrary
from VO.ProjectVO import ProjectVO
from VO.ProductVO import ProductVO
from VO.RoomVO import RoomVO
from VO.RoomLibVO import RoomLibVO
from Service.ProjectService import ProjectService


## 时间转换
def datetime_filter(t):
    delta = int(time.time() - t)
    if delta < 60:
        return u'1分钟前'
    if delta < 3600:
        return u'%s分钟前' % (delta // 60)
    if delta < 86400:
        return u'%s小时前' % (delta // 3600)
    if delta < 604800:
        return u'%s天前' % (delta // 86400)
    dt = datetime.fromtimestamp(t)
    return u'%s年%s月%s日' % (dt.year, dt.month, dt.day)

class TemplateRendering(object):

    def render_html_file(self, template_name, **kwargs):
         template_dirs = []
         if self.settings.get('template_path', ''):
             template_dirs.append(self.settings['template_path'])
         env = Environment(loader=FileSystemLoader(template_dirs))
         env.filters['datetime'] = datetime_filter
         try:
             template = env.get_template(template_name)
         except TemplateNotFound:
             raise TemplateNotFound(template_name)
         content = template.render(kwargs)
         return content

class BaseHandler(RequestHandler, TemplateRendering):
    def set_default_headers(self):
        self.set_header("Access-Control-Allow-Origin", "*")
        self.set_header("Access-Control-Allow-Headers",
                        "x-requested-with,access_token")  # 这里要填写上请求带过来的Access-Control-Allow-Headers参数，如access_token就是我请求带过来的参数
        self.set_header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")  # 请求允许的方法
        self.set_header("Access-Control-Max-Age", "3600")  # 用来指定本次预检请求的有效期，单位为秒，，在此期间不用发出另一条预检请求。
        #self.set_header("Content-Type", "application/json; charset=UTF-8")
    # 定义一个响应OPTIONS 请求，不用作任务处理
    def options(self):
        pass

    # def get(self):
    #     self.write_error(404)
    def render_template(self, template_name, **kwargs):

        kwargs.update({

        "settings": self.settings,

        "STATIC_URL": self.settings.get("static_url_prefix", "/static/"),

        "request": self.request,

        "current_user": self.current_user,

        "xsrf_token": self.xsrf_token,

        "xsrf_form_html": self.xsrf_form_html
        })

        content = self.render_html_file(template_name, **kwargs)
        self.finish(content)

    # def write_error(self, status_code, **kwargs):
    #     if status_code == 404:
    #         print(404)
    #         self.render('public/404.html')
    #     elif status_code == 500:
    #         self.render('public/500.html')
    #     else:
    #         self.write('error:' + str(status_code))

class ProjectAddItem(BaseHandler):
    async def post(self):
        '''
        qdsoftid    工厂id
        userid    用户id
        sNo    方案编号
        sName    方案名
        sDes    方案描述
        data    方案数据
        Extra    方案其他数据
        preview    视图
        :return:
        '''
        qdsoftid = self.get_argument('qdsoftid', '')
        userid = self.get_argument('userid', '')
        sNo = self.get_argument('sNo', '')
        sName = self.get_argument('sName', '')
        sDes = self.get_argument('sDes', '')
        data = self.get_argument('data', '')
        Extra = self.get_argument('extra', '')
        preview = self.get_argument('preview', '')

        if sName:
            guid = MyUtil.getguid()
            project = Project(qdsoftid=qdsoftid, userid=userid,
                              guid=guid, sNo=sNo, sName=sName,
                              sDes=sDes, data=data, Extra=Extra,
                              preview=preview)
            Res = await ProjectService.addproject(project)
            self.write(ResultVOUtil.result(Res))
        else:
            self.write(ResultVOUtil.error('sName is null!'))

class ProjectDeleteItem(BaseHandler):
    async def post(self):
        '''
        参数 guid
        :return:
        '''
        guid = self.get_argument('guid', None)
        if guid is not None:
            await Project.delete('guid', guid)
            await Product.delete('project_guid', guid)
            self.write(ResultVOUtil.success())
        else:
            self.write(ResultVOUtil.error('guid is null!'))

class ProjectFindItem(BaseHandler):
    async def post(self, **kw):
        id = self.get_argument('id', None)
        userid = self.get_argument('userid', '')
        qdsoftid = self.get_argument('qdsoftid', '')
        if userid and qdsoftid:
            alldata = await Project.findproject(userid=userid, qdsoftid=qdsoftid)
            alldata = ProjectVO.resultvo(alldata)
            self.write(ResultVOUtil.success(alldata))
            return
        if id:
            id = int(id)
            alldata = await Project.findproject(isdata=True, id=id)
            alldata = ProjectVO.resultvo(alldata)
            self.write(ResultVOUtil.success(alldata))
            return
        if qdsoftid:
            alldata = await Project.findproject(qdsoftid=qdsoftid)
            alldata = ProjectVO.resultvo(alldata)
            self.write(ResultVOUtil.success(alldata))
            return
 # project = await Project.find(id)
    # for key in list(data.keys()):
    #     project[key] = data[key]
    # await project.update()
    # return
class ProjectChangeItem(BaseHandler):
    async def post(self):
        id = self.get_argument('id', None)
        datajson = self.get_argument('data', None)
        if datajson is None:
            self.write(ResultVOUtil.error(errorinfo='argv data is None!', code=-2))
            return
        try:
            data = json.loads(datajson)
        except json.decoder.JSONDecodeError as e:
            self.write(ResultVOUtil.error(errorinfo=str(e), code=-2))
            return

        projectnum = await Project.findNumber('count(id)',where='`id`=%s',args=[int(id)])
        if projectnum is None or projectnum == 0:
            self.write(ResultVOUtil.error(errorinfo='id is not exist in table!!!', code=-1))
            return
        elif projectnum == 1:
            await Project.updateproject(data, id=id)
            self.write(ResultVOUtil.success())
            return
        else:
            self.write(ResultVOUtil.error(code=-1))
            return

class ProjectFindPublicItem(BaseHandler):
    async def post(self):
        userid = self.get_argument('userid', '')
        qdsoftid = self.get_argument('qdsoftid', '')
        if userid and qdsoftid:
            alldata = await Project.findpublic(userid=userid, qdsoftid=qdsoftid)
            alldata = ProjectVO.resultvo(alldata)
            self.write(ResultVOUtil.success(alldata))
            return
        else:
            self.write(ResultVOUtil.error(errorinfo='NoUSER in tables!!!'))

class ProjectSetAuthorityData(BaseHandler):
    async def post(self):
        id = int(self.get_argument('id', 0))
        authority = int(self.get_argument('authority', 0))
        if id and (authority in [0, 1, 2, 3]):
            projectnum = await Project.findNumber('count(id)', where='`id`=%s', args=[int(id)])
            if projectnum is None or projectnum == 0:
                self.write(ResultVOUtil.error(errorinfo='id is not exist in table!!!'))
                return
            elif projectnum == 1:
                data = {'authority':authority}
                await Project.updateproject(data, id=id)
                self.write(ResultVOUtil.success())
                return
            else:
                self.write(ResultVOUtil.error())
                return
        else:
            self.write(ResultVOUtil.error(errorinfo='authority error!!!'))

class ProjectCloneData(BaseHandler):
    async def post(self):
        guid = self.get_argument('guid', None)
        if guid:
            project = await Project.findprojectandproductdata(isdata = True, guid=guid)
            if project is None:
                self.write(ResultVOUtil.error(errorinfo='guid is not in table!'))
                return
            if 'project' in project:
                guidmap = {}
                project['project']['guid'] = MyUtil.getguid()
                if 'products' in project:
                    productlist = project['products']
                    for i in range(0, len(productlist)):
                        product = productlist[i]
                        if 'project_guid' in product:
                            product['project_guid'] = project['project']['guid']
                        if 'guid' in product:
                            productguid = MyUtil.getguid()
                            guidmap[product['guid']] = productguid
                            product['guid'] = productguid
                datatext = json.dumps(project, ensure_ascii=False, default=str).encode('utf8')
                for oldguid, newguid in guidmap.items():
                    datatext = datatext.replace(oldguid.encode('utf8'), newguid.encode('utf8'))
                datajson = json.loads(datatext)
                isupdate = await Project.updateprojectandproduct(datajson,isinsert=True)
                if isupdate:
                    projects = await Project.findproject(guid=datajson['project']['guid'])
                    if projects:
                        projects = ProjectVO.resultvo(projects)
                        self.write(ResultVOUtil.success(projects))
                        return
            self.write(ResultVOUtil.error(errorinfo='clone fail'))
            return
        else:
            self.write(ResultVOUtil.error(errorinfo='argv_guid is null!'))

class ProjectGetData(BaseHandler):
    async def post(self):
        guid = self.get_argument('guid', None)
        if guid:
            project = await Project.findprojectandproductdata(isdata=True, guid=guid)
            self.write(ResultVOUtil.success(project))
        else:
            self.write(ResultVOUtil.error(errorinfo='argv_guid is null!'))

class ProjectSetData(BaseHandler):
    async def post(self):
        datajson = self.get_argument('data', '')
        datajson = unquote(datajson, 'utf-8')
        if datajson is None:
            self.write(ResultVOUtil.error(errorinfo='data is None!', code=-2))
            return
        try:
            data = json.loads(datajson)

            project = await Project.updateprojectandproduct(data)

            if project:
                self.write(ResultVOUtil.success())
                return
            self.write(ResultVOUtil.error(errorinfo=str('save error')))
            return
        except json.JSONDecodeError as e:
            self.write(ResultVOUtil.error(errorinfo=str(e)))
            return

class ProductAddItem(BaseHandler):
    async def post(self):
        guid = self.get_argument('guid', '')
        project_guid = self.get_argument('project_guid', 0)
        sNo = self.get_argument('sNo', '')
        sName = self.get_argument('sName', '')
        sDes = self.get_argument('sDes', '')
        data = self.get_argument('data', '')
        Extra = self.get_argument('extra', '')
        if sName:

            product = Product(project_guid=project_guid, guid=guid, sNo=sNo, sName=sName,
                              sDes = sDes, data = data, Extra=Extra)
            await product.save()
            Res = {'result': 1, 'guid': guid}
            self.write(ResultVOUtil.result(Res))
        else:
            self.write(ResultVOUtil.error(errorinfo='sName is null!'))

class ProductDeleteItem(BaseHandler):
    async def post(self):
        id = self.get_argument('id', None)
        if id is not None:
            await Product.delete('id', id)
            self.write(ResultVOUtil.success())
        else:
            self.write(ResultVOUtil.error(errorinfo='guid is null!'))

class ProductFindItem(BaseHandler):
    async def post(self):
        id = self.get_argument('id', None)
        if id:
            id = int(id)
            product = await Product.find(id)
            product = ProductVO.resultvo(product)
            self.write(ResultVOUtil.success(product))
            return

class ProductChangeItem(BaseHandler):
    async def post(self):
        id = self.get_argument('id', None)
        datajson = self.get_argument('data', None)
        if datajson is None:
            self.write(ResultVOUtil.error(errorinfo='data is None!', code=-2))
            return
        try:
            data = json.loads(datajson)
        except json.decoder.JSONDecodeError as e:
            self.write(ResultVOUtil.error(errorinfo=str(e), code=-2))
            return
        productnum = await Product.findNumber('count(id)',where='`id`=%s',args=[int(id)])
        if productnum is None or productnum == 0:
            self.write(ResultVOUtil.error(errorinfo='id is not exist in table!!!'))
            return
        elif productnum == 1:
            await Product.updateproduct(data, id=id)
            self.write(ResultVOUtil.success())
            return
        else:
            self.write(ResultVOUtil.error())
            return

class RoomAddItem(BaseHandler):
    async def post(self):
        guid = MyUtil.getguid()
        qdsoftid = self.get_argument('qdsoftid', '')
        userid = self.get_argument('userid', '')
        sName = self.get_argument('sName', '')
        sDes = self.get_argument('sDes', '')
        data = self.get_argument('data', '')
        previewfile = self.request.files.get('preview', None)
        preview = ''
        if previewfile:
            for meta in previewfile:
                previewFileGuid = MyUtil.getguid()
                imageext = meta['content_type'].split("/")[1]
                imagefilename = previewFileGuid + '.' + imageext
                previewfilepath = os.path.join(conf.UPLOADPREVIEWFILE, imagefilename)
                # 有些文件需要已二进制的形式存储，实际中可以更改

                with open(previewfilepath, 'wb') as up:
                    up.write(meta['body'])
                print(imagefilename)
                preview = 'http://qdsoft.huaguangsoft.com/' + 'roomimage' + '/' + imagefilename
        if sName:

            room = Room(guid=guid, qdsoftid=qdsoftid, userid=userid, sName=sName,
                              sDes = sDes, data = data, preview=preview)
            await room.save()

            res = {'result': 1, 'guid': guid}
            self.write(ResultVOUtil.result(res))
        else:
            self.write(ResultVOUtil.error(errorinfo='sName is null!'))

class RoomDeleteItem(BaseHandler):
    async def post(self):
        guid = self.get_argument('guid', None)
        if guid:
            await Room.deleteroom('guid', guid)
            self.write(ResultVOUtil.success())
        else:
            self.write(ResultVOUtil.error(errorinfo='guid is null!'))

class RoomFindItem(BaseHandler):
    async def post(self):
        id = self.get_argument('id', 0)
        userid = self.get_argument('userid', '')
        qdsoftid = self.get_argument('qdsoftid', '')
        isone = self.get_argument('isone', False)
        if qdsoftid and userid:
            room = await Room.findrooms(userid=userid, qdsoftid=qdsoftid)
            room = RoomVO.resultvo(room)
            self.write(ResultVOUtil.success(room))
            return
        if id:
            id = int(id)
            room = await Room.findrooms(id=id)
            room = RoomVO.resultvo(room)
            self.write(ResultVOUtil.success(room))
            return
        if qdsoftid:
            room = await Room.findrooms(qdsoftid=qdsoftid)
            room = RoomVO.resultvo(room)
            self.write(ResultVOUtil.success(room))
            return
        else:
            self.write(ResultVOUtil.error(errorinfo='NoData in tables!!!'))

class RoomChangeItem(BaseHandler):
    async def post(self):
        id = self.get_argument('id', None)
        datajson = self.get_argument('data', None)
        if datajson is None:
            self.write(ResultVOUtil.error(errorinfo='data is None!', code=-2))
            return
        try:
            data = json.loads(datajson)
        except json.decoder.JSONDecodeError as e:
            self.write(ResultVOUtil.error(errorinfo=str(e), code=-2))
            return
        previewfile = self.request.files.get('preview', None)  #
        if previewfile:
            for meta in previewfile:
                previewFileGuid = MyUtil.getguid()
                imageext = meta['content_type'].split("/")[1]
                imagefilename = previewFileGuid + '.' + imageext
                previewfilepath = os.path.join(conf.UPLOADPREVIEWFILE, imagefilename)
                # 有些文件需要已二进制的形式存储，实际中可以更改
                with open(previewfilepath, 'wb') as up:
                    up.write(meta['body'])
                print(imagefilename)
                preview = 'http://qdsoft.huaguangsoft.com/' + 'roomimage' + '/' + imagefilename
                data['preview'] = preview
        roomnum = await Room.findNumber('count(id)',where='`id`=%s',args=[int(id)])
        if roomnum is None or roomnum == 0:
            self.write(ResultVOUtil.error(errorinfo='id is not exist in table!!!'))
            return
        elif roomnum == 1:
            await Room.updateitems(data, id=id)
            self.write(ResultVOUtil.success())
            return
        else:
            self.write(ResultVOUtil.error())
            return

'''
房型库接口
'''
class RoomLibraryAddItem(BaseHandler):
    async def post(self):
        roomid = self.get_argument('roomid', '')
        label = self.get_argument('label', '')
        roomnums = self.get_argument('roomnums', '')
        area = self.get_argument('area', '')
        address = self.get_argument('address', '')
        propertyname = self.get_argument('propertyname', '')
        if roomid:
            roomlibrary = RoomLibrary(roomid=roomid,label=label,
                                      roomnums=roomnums,area=area,
                                      address=address,propertyname=propertyname)
            await roomlibrary.save()
            await Room.updateitems({"isstore":'1'}, id=roomid)
            self.write(ResultVOUtil.success())
            return
        else:
            self.write(ResultVOUtil.error(errorinfo='roomid is null!'))

class RoomLibraryDeleteItem(BaseHandler):
    async def post(self):
        argvid = self.get_argument('id', None)
        if argvid:
            id = int(argvid)
            await RoomLibrary.deleteroom('id', id)
            self.write(ResultVOUtil.success())
        else:
            self.write(ResultVOUtil.error(errorinfo='argvid is null!'))

class RoomLibraryChangeItem(BaseHandler):
    async def post(self):
        argvid = self.get_argument('id', None)
        datajson = self.get_argument('data', "{}")
        id = int(argvid)
        if datajson is None:
            self.write(ResultVOUtil.error(errorinfo='data is None!', code=-2))
            return
        try:
            data = json.loads(datajson)
        except json.decoder.JSONDecodeError as e:
            self.write(ResultVOUtil.error(errorinfo=str(e), code=-2))
            return

        roomlibrarynum = await RoomLibrary.findNumber('count(id)', where='`id`=%s', args=[int(id)])
        Res = {}
        if roomlibrarynum is None or roomlibrarynum == 0:
            self.write(ResultVOUtil.error(errorinfo='id is not exist in table!!!'))
            return
        elif roomlibrarynum == 1:
            await RoomLibrary.updateitems(data, id=id)
            self.write(ResultVOUtil.success())
            return
        else:
            self.write(ResultVOUtil.error())
            return

class RoomLibraryFindItem(BaseHandler):
    async def post(self):
        argvid = self.get_argument('id', None)
        if argvid:
            id = int(argvid)
            roomlibrary = await RoomLibrary.findroomlibrary(id=id)
            roomlibrary = RoomLibVO.resultvo(roomlibrary)
            result = {"datalist": roomlibrary, "state": 1}
            self.write(ResultVOUtil.result(result))

## 获取页码信息
def get_page_index(page_str):
    p = 1
    try:
        p = int(page_str)
    except ValueError as e:
        pass
    if p < 1:
        p = 1
    return p

def getcondition(searchitems, arearange):
    searchsql = ''
    for index, value in enumerate(searchitems):
        if value[1] is None: continue
        if value[0] == 'propertyname':
            searchsql = searchsql + " instr(%s, '%s')>0 " % (value[0], value[1]) #%s like '%%%s%%'

        elif value[0] == 'area':
            if arearange[0] == arearange[1] == '0': continue
            if arearange[0] != '0' and arearange[1] == '-1':
                searchsql = searchsql + " cast(%s as DECIMAL) >= %f " % (value[0], float(arearange[0]))
            else:
                searchsql = searchsql + " cast(%s as DECIMAL) BETWEEN %f and %f " % (
                    value[0], float(arearange[0]), float(arearange[1]))
        else:
            searchsql = searchsql + " %s = '%s' " % (value[0], value[1])

        if index < len(searchitems) - 1: searchsql = searchsql + 'and'
    if searchsql=='':return False
    return searchsql

class RoomLibraryStoreHouse(BaseHandler):
    async def post(self, *args, **kwargs):
        pageNo = self.get_argument("pageNo", 1)  # 页码
        pageSize = self.get_argument("pageSize", 10)  # 页面大小
        pageSize = int(pageSize)
        roomnums = self.get_argument('roomnums', None)
        arealeft = self.get_argument('arealeft', '0')
        arearight = self.get_argument('arearight', '0')
        propertyname = self.get_argument('propertyname', None)
        address = self.get_argument('address', None)

        arearange = [arealeft, arearight]  # 0,60;>60:60,-1
        searchitems = []  # 筛选列表
        if roomnums is not None: searchitems.append(['roomnums', roomnums])
        if propertyname is not None: searchitems.append(['propertyname', propertyname])
        if address is not None: searchitems.append(['quickdraw_software_roomlibrary.address', address])
        if not (arealeft == arearight == '0'): searchitems.append(['area', 0])
        page_index = get_page_index(pageNo)  # 获取页码信息

        condition = getcondition(searchitems, arearange)
        num = await RoomLibrary.findNumber('count(id)',condition)  # 返回 id列数量


        pages = int(math.ceil(num * 1.0 / pageSize))  # 需要的页数
        logger.info('pages={},pageNo={}'.format(pages, page_index))
        if pages == 0: pages = 1
        if page_index > pages: page_index = pages

        p = Page(num, page_index, int(pageSize))
        if num == 0:
            roomlibrarys = []
        else:
            # p.offset 该页码的第一条数据库位置, p.limit 取多少条
            roomlibrarys = await RoomLibrary.findAll(where=condition, orderBy='id desc', limit=(p.offset, p.limit))
        roomlibrarys = RoomLibVO.resultvo(roomlibrarys)
        result = {"datalist": roomlibrarys,
                  "state": 1, "pages": pages,
                  "pageNo": page_index, "totalSize": num,
                  "info": "成功"}

        self.write(ResultVOUtil.result(result))
